package com.code.refactoring.重构demo.状态机扭转.check;

/**
 * @author wangxi03 created on 2021/4/29 10:54 上午
 * @version v1.0
 */

import com.code.refactoring.重构demo.状态机扭转.entity.ServiceResult;
import com.code.refactoring.重构demo.状态机扭转.entity.StateContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 校验器的执行器
 */
@Slf4j
@Component
public class CheckerExecutor<T, C> {

    private static final ExecutorService executorService = Executors.newFixedThreadPool(2);

    /**
     * 执行并行校验器，
     * 按照任务投递的顺序判断返回。
     */
    public ServiceResult<T> parallelCheck(List<Checker<T, C>> checkers, StateContext<C> context) {
        if (!CollectionUtils.isEmpty(checkers)) {
            if (checkers.size() == 1) {
                return checkers.get(0).check(context);
            }
            List<Future<ServiceResult<T>>> resultList = Collections.synchronizedList(new ArrayList<>(checkers.size()));
            checkers.sort(Comparator.comparingInt(Checker::order));
            for (Checker<T, C> c : checkers) {
                Future<ServiceResult<T>> future = executorService.submit(() -> c.check(context));
                resultList.add(future);
            }
            for (Future<ServiceResult<T>> future : resultList) {
                try {
                    ServiceResult<T> sr = future.get();
                    if (!sr.isSuccess()) {
                        return sr;
                    }
                } catch (Exception e) {
                    log.error("parallelCheck executor.submit error.", e);
                    throw new RuntimeException(e);
                }
            }
        }
        return new ServiceResult<>();
    }

    public ServiceResult<T> paramCheck(List<Checker<T, C>> checkers, StateContext<C> context) {
        return null;
    }

    public ServiceResult<T> serialCheck(List<Checker<T, C>> checkers, StateContext<C> context) {
        return null;
    }
}



